﻿using Dijiang.Errors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dijiang.Values
{
    public class DClosure : DFunction
    {
        public DValue formals;
        public DValue body;

        public CmdEnv local;

        public DClosure(DValue formals, DValue body) : base()
        {
            this.formals = formals;
            this.body = body;

            local = new CmdEnv();
        }

        public override DValue Call(CmdEnv env, DSequence args)
        {
            var f = (DSequence)formals;

            int given = args.Count;
            int total = f.Count;

            while (args.Count > 0)
            {
                if (f.Count <= 0)
                {
                    return new WrongArgumentsError(given, total);
                }

                var sym = (DSymbol)f.Pop();
                var val = args.Pop();

                local.Put(sym.sym, val);
            }

            if (f.Count <= 0)
            {
                local.parent = env;
                return local.Evaluate(body.Copy());
            }
            else
            {
                return Copy();
            }
        }

        public override DValue Copy()
        {
            var result = new DClosure(formals.Copy(), body.Copy());
            result.local = local.Copy();
            return result;
        }

        public override bool Equals(DValue? other)
        {
            // TODO: Implement lambda equal judge.
            return false;
        }

        public override DValue Eval(CmdEnv env)
        {
            return this;
        }

        public override string ToString()
        {
            return "<Closure>";
        }
    }
}
